/* Dismantle and free the entire VM subsystem for a process */

#include <assert.h>
#include <sel4/sel4.h>

#include "../ut_manager/ut.h"
#include "../frametable.h"
#include "../macros.h"
#include "../picoro.h"
#include "../task.h"
#include "../vmem_layout.h"

#include "../debug.h"
#define verbose SOS_DEBUG_PROC_DELETE
#include <sys/debug.h>
#include <sys/panic.h>

#include "../swaptable.h"

int sos_pager_destroy(sos_pcb *pcb) {
    int err = 0;
    // delete each region
    err = sos_page_free_all(pcb);
    if (!err && pcb->regions != NULL) {
        dprintf(6, "pager_destroy: ERROR, region list not cleaned up\n");
    } else if (err) {
        dprintf(6, "pager_destroy: page_free_all failed (%d)\n", err);
    }

    // free pt_caps, unmap all page tables etc
    dprintf(6, "pager_destroy: destroying page tables\n");
    err = sos_pt_list_destroy(&(pcb->pt_caps));
    if (err) {
        dprintf(6, "pager_destroy: pt_list_destroy failed (%d)\n", err);
    }

    // Delete vspace cap
    dprintf(6, "pager_destroy: deleting vspace cap\n");
    err = cspace_delete_cap(cur_cspace, pcb->seL4_pd);
    pcb->seL4_pd = NULL;
    if (err) {
        dprintf(6, "pager_destroy: could not delete seL4_pd from cspace (%d)\n",
                err);
    }

    // return raw vspace memory to ut
    dprintf(6, "pager_destroy: returing vspace memory to ut\n");
    ut_free(pcb->seL4_pd_addr, seL4_PageDirBits);
    pcb->seL4_pd_addr = NULL;

    // free sos_pd
    dprintf(6, "pager_destroy: discarding sos_pd\n");
    err = frame_free((seL4_Word) pcb->sos_pd);
    pcb->sos_pd = NULL;
    if (err) {
        dprintf(6, "pager_destroy: could not free SOS PD frame (%d)\n", err);
    }

    return err;
}
